with Ada.Calendar, Moteur_Physique, Moteur_Graphique, Sdl_Video;
use Ada.Calendar, Moteur_Physique, Moteur_Graphique, Sdl_Video;

with Sdl_Events_H, Sdl_Keysym_H, Sdl_H;
use Sdl_Events_H, Sdl_Keysym_H;
with Interfaces.C; use Interfaces.C;

with Ada.Text_Io; use Ada.Text_Io;

with Vecteurs; use Vecteurs;
with Billes; use Billes;
with Scenes; use Scenes;

procedure Main is

   -- Partie SDL ----------------------------------------------------
   Isdl : Interfaces.C.Int;
   Ecran : Sdl_Surface;
   ------------------------------------------------------------------

   Dernier_Temps : Time;
   Rayon_Bille : constant := 6.0;

   -- constante de gravitation
   G : constant Long_Float := 100.0;
   Gravite : constant Vecteur_Type := (0.0, -G);

   -- la scene contenant les objets et les forces
   Scene : Scene_Type;
   Event : aliased Sdl_Event;
   Depart : Time;

   Frames_Par_Seconde : constant := 60.0; -- nombre maximum d'image par seconde

   Demarrer : Boolean := False;
   Ok : Boolean := False;

   Largeur_Ecran : constant := 500;
   Hauteur_Ecran : constant := 500;

   Temps_Ecoule : Float := 0.0;

   B : Bille_Type := New_Bille (Rayon_Bille, (0.0, 0.0), (0.0, 0.0), (0, 0, 0) , 1.0);

   Fps       : Integer;

   task Tache_Affichage is
      entry Afficher (Scene : in Scene_Type);
   end Tache_Affichage;


   task body Tache_Affichage is
      Copie   : Scene_Type;
      Next_Time : Time := Clock;
      Last_Time : Time := Clock;
   begin
      loop
         accept Afficher (Scene : Scene_Type) do
            Copie := Scene;
         end Afficher;
         Fill_Rect (Ecran, R => 200, G => 200, B => 200);
         Dessiner (Ecran, Copie);
         Flip (Ecran);
      end loop;
   end Tache_Affichage;



   task Tache_Gestion_Physique;

   task body Tache_Gestion_Physique is
      Next_Time : Time := Clock;
      last_time : time := clock;
   begin
      loop
         if Demarrer then
            -- mise jour des positions des billes --
            Update (Scene);

            delay until Next_Time;
            -- mise à jour de l'affichage
            Tache_Affichage.Afficher (Scene);

            Next_Time := clock + Duration (1.0 / Frames_Par_Seconde);

            Fps := Integer (1.0 / (Clock - Last_Time));
            Last_Time := Clock;
         else
            delay(0.01);
         end if;
      end loop;
   end Tache_Gestion_Physique;


   task Tache_Fps;
   task body Tache_Fps is
      Next_Time : Time := Clock;
   begin
      loop
         if Demarrer then
            delay until Next_Time;
            put_line ("fps=" & Integer'Image (Fps));
            Next_Time := Clock + Duration (0.5);
         else
            delay (0.01);
         end if;
      end loop;
   end tache_fps;


begin
   Isdl := Sdl_H.Sdl_Init (Sdl_H.Sdl_Init_Video);
   Set_Icon (Sdl_Load_Bmp ("icon.bmp"));
   Ecran := Set_Video_Mode (Largeur_Ecran, Hauteur_Ecran, 32, (Hwsurface, Doublebuf)); --, Fullscreen));
   Set_Caption ("Collisions");

   Scene := New_Scene (Largeur_Ecran, Hauteur_Ecran, Gravite);

   for I in 1 .. 10 loop
      for J in 1 .. 20 loop
         --           if J mod 2 = 0 then
         B.Pos := (-Long_Float (J) * 2.5 * Rayon_Bille + 400.0, Long_Float (I) * 2.5 * Rayon_Bille );
         B.Couleur := (255, 0, 0);
         B.Vitesse := (200.0, 0.0);
         Ajouter (Scene, B);
         --           else
         --              B.Pos := (Get_Width (Scene) - long_float (J) * 2.5 * Rayon_Bille, long_float (I) * 2.5 * Rayon_Bille + 100.0);
         --              B.Vitesse := (-100.0, 50.0);
         --              B.Couleur := (0, 0, 255);
         --              Ajouter (Scene, B);
         --           end if;
      end loop;
   end loop;

   -- ajout de la grosse bille
   B.Fixe := True;
   B.Pos := (200.0, 100.0);
   B.Rayon := 20.0;
   B.Masse := 1000.0;
   B.Vitesse := (0.0, 0.0);
   B.Couleur := (255, 128, 0);
   Ajouter (Scene, B);

   Tache_Affichage.Afficher (Scene);

   Depart := Clock;

   loop
      if Sdl_Pollevent (Event'Access) then
         case Type_Of (Event) is
         when Sdl_Quit =>
            abort Tache_Fps;
            abort Tache_Affichage;
            abort Tache_Gestion_Physique;
            exit;
         when Sdl_Keydown =>
            case Event.Key.Keysym.Sym is
            when Sdlk_Escape =>
               abort Tache_Fps;
               abort Tache_Affichage;
               abort Tache_Gestion_Physique;
               exit;
               when Sdlk_Space =>
                  Depart := Clock;
                  Demarrer := not Demarrer;
               when others =>
                  null;
               end case;
         when others =>
            null;
         end case;
      end if;

--        if Demarrer then
--           if Ok = false and then Float (Dernier_Temps - Depart) > 30.0 then
--              B.Fixe:= False;
--              B.Pos := (100.0, 400.0);
--              B.Couleur := (255, 255, 0);
--              B.Vitesse := (100.0, -50.0);
--              Ajouter (Scene, B);
--              Ok := True;
--           end if;
--        end if;

      delay (0.01);

   end loop;

   Sdl_H.Sdl_Quit;

end Main;
